package com.enba.mallapi.config;

import com.enba.boot.core.exception.BizException;
import com.enba.boot.core.exception.NotLoginException;
import com.enba.boot.jwt.JwtHelper;
import com.enba.boot.web.properties.WebProperties;
import com.enba.mallapi.annotation.CurrentUser;
import io.jsonwebtoken.Claims;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

public class CurrentUserObjectMethodArgumentResolver implements HandlerMethodArgumentResolver {

  private JwtHelper jwtHelper;
  private WebProperties webProperties;

  public CurrentUserObjectMethodArgumentResolver(JwtHelper jwtHelper, WebProperties webProperties) {
    this.jwtHelper = jwtHelper;
    this.webProperties = webProperties;
  }

  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    // 只处理对象类型的参数（非基本类型、非集合、非数组等）
    Class<?> parameterType = parameter.getParameterType();
    return !parameterType.isPrimitive()
        && !isWrapperType(parameterType)
        && !parameterType.isArray()
        && !Collection.class.isAssignableFrom(parameterType)
        && !Map.class.isAssignableFrom(parameterType);
  }

  @Override
  public Object resolveArgument(
      MethodParameter parameter,
      ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest,
      WebDataBinderFactory binderFactory)
      throws Exception {
    // 获取参数类型
    Class<?> parameterType = parameter.getParameterType();

    // 创建对象实例（假设有无参构造方法）
    Object targetObject = parameterType.getDeclaredConstructor().newInstance();

    // 遍历所有字段，检查是否有 @CurrentUser 注解
    for (Field field : parameterType.getDeclaredFields()) {
      if (field.isAnnotationPresent(CurrentUser.class)) {
        // 从上下文中获取用户 ID
        Object userId = getCurrentUserIdFromContext(webRequest);

        // 设置字段值（需要设置 accessible=true）
        field.setAccessible(true);
        field.set(targetObject, userId);
      }
    }

    return targetObject;
  }

  // 从上下文中获取用户 ID
  private Object getCurrentUserIdFromContext(NativeWebRequest webRequest) {
    // 从 NativeWebRequest 中获取请求头
    String token = webRequest.getHeader(webProperties.getHearName());

    if (StringUtils.isBlank(token)) {
      BizException.throwEx("token is null");
    }

    // 校验token
    if (!jwtHelper.validateToken(token)) {
      // 非法token 包括token过期
      NotLoginException.throwEx();
    }

    // 解析token
    Claims claims = jwtHelper.parseToken(token);

    // 用户id
    return claims.get("userId");
  }

  // 判断是否为包装类（如 Integer, Long, Boolean 等）
  private boolean isWrapperType(Class<?> clazz) {
    return clazz.equals(Boolean.class)
        || clazz.equals(Character.class)
        || clazz.equals(Byte.class)
        || clazz.equals(Short.class)
        || clazz.equals(Integer.class)
        //        || clazz.equals(Long.class)
        || clazz.equals(Float.class)
        || clazz.equals(Double.class)
        || clazz.equals(Void.class);
  }
}
